#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <time.h>

int main(int argc, char *argv[]){
    int J_ORDER, J_ROW_TEST, J_ITE_MAX, i= 0, j= 0, k, iteracoes= 0;
    float J_ERROR, somatoria= 0, erro= 0, maior_X, aux= 0, aux2;

    FILE *f = fopen(argv[1], "r");
    if (f == NULL)
        return 0;

    fscanf(f, "%d %d %f %d", &J_ORDER, &J_ROW_TEST, &J_ERROR, &J_ITE_MAX);

    float **A, B[J_ORDER], B_[J_ORDER], DIF[J_ORDER], X[2][J_ORDER];
    double inicio = clock();

    A = (float**)malloc(sizeof(float*)*J_ORDER);
    for (i=0; i<J_ORDER; i++) A[i] = (float*)malloc(sizeof(float)*J_ORDER);

    for(i= 0; i < J_ORDER; i++) {
        for(j= 0; j < J_ORDER; j++) {
            fscanf(f, "%f", &A[i][j]);
        }
    }

    for(i= 0; i < J_ORDER; i++) {
        fscanf(f, "%f", &B[i]);
    }
    fclose(f);

    /* zera as matrizes */
    for(i= 0; i < J_ORDER; i++) {
            X[0][i]= 0;
            X[1][i]= 0;
            DIF[i]= 0;
    }

    /* calcula a primeira linha da matriz de iterações */
    for(i= 0; i < J_ORDER; i++) {
        B_[i]= B[i]/A[i][i];
        X[0][i]= B_[i];
    }

    /* calcula até alcançar o erro desejado */
    iteracoes= 0;
    erro= 10000000;

    while(erro > J_ERROR && iteracoes < J_ITE_MAX) {
        iteracoes++;
        erro= 0;
        maior_X= 0;

        for(j = 0; j < J_ORDER; j++)
            X[0][j] = X[1][j];

        for(j= 0; j < J_ORDER; j++) {
            somatoria= 0;
            for(k= 0; k < J_ORDER; k++) {
                if(k != j){
                    somatoria += (A[j][k]/A[j][j])*X[0][k];
                }
            }
            X[1][j]= B_[j] - somatoria;

            DIF[j]= fabs(X[1][j] - X[0][j]);

            if(DIF[j] > erro)
                erro= DIF[j];

            if(fabs(X[1][j]) > maior_X)
                maior_X= (float)fabs(X[1][j]);
        }
        erro /= maior_X;
    }

    for(i= 0; i < J_ORDER; i++)
          aux += A[J_ROW_TEST][i]* X[0][i];

    double fim = clock();

    if ((ceil(aux)- aux)>= 0.5) aux2= floor(aux);
    else aux2= ceil(aux);

    printf("\n---------------------------------------------------------\nIterations: %d\nRow Test: %d => [%f] =? %f\n---------------------------------------------------------\nTempo: %lf segundos%.4lf\n", iteracoes-1, J_ROW_TEST, aux, aux2, (fim - inicio)/CLOCKS_PER_SEC);
    return 0;

}
